{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "95f0a171",
   "metadata": {},
   "source": [
    "(workflow-basics)=\n",
    "# Workflow: Basics\n",
    "\n",
    "If you followed the previous chapters, you will now have some experience running Python code. We didn't give you many details, but you've obviously figured out the basics, or you would've thrown this book away in frustration! Frustration is natural when you start programming in Python, because it is such a stickler for punctuation, and even one character out of place will cause it to complain. But while you should expect to be a little frustrated, take comfort in that this experience is both typical and temporary: it happens to everyone, and the only way to get over it is to keep trying.\n",
    "\n",
    "Before we go any further, let's make sure you've got a solid foundation in running Python code, and that you know about some of the most helpful Visual Studio Code features for working with Python."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "52bd88aa",
   "metadata": {},
   "source": [
    "## Coding Basics\n",
    "\n",
    "Let's review some basics we've omitted thus far in the interests of getting you up to speed as quickly as possible. You can use Python as a calculator:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "23465996",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(1 / 200 * 30)\n",
    "print((59 + 73 + 2) / 3)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "0f0ee026",
   "metadata": {},
   "source": [
    "The extra package **numpy** contains many of the additional mathematical operators that you might need. If you don't already have **numpy** installed, open up the terminal in Visual Studio Code (go to \"Terminal -> New Terminal\" and then type `pip install numpy` into the terminal then hit return). Once you have **numpy** installed, you can import it and use it like this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bdd3c2c0",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "print(np.sin(np.pi / 2))"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "735168ca",
   "metadata": {},
   "source": [
    "You can create new objects with the assignment operator `=`. You should think of this as copying the value of whatever is on the right-hand side into the variable on the left-hand side."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cead1264",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = 3 * 4\n",
    "print(x)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "95cdd9bf",
   "metadata": {},
   "source": [
    "There are several structures in Python that capture multiple objects simultaneously but perhaps the most common is the *list*, which is designated by *square brackets*."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "91a44d83",
   "metadata": {},
   "outputs": [],
   "source": [
    "primes = [1, 2, 3, 5, 7, 11, 13]\n",
    "print(primes)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "4978f028",
   "metadata": {},
   "source": [
    "To do basic arithmetic on a list, use a *list comprehension* which has the structure \"for every element in this list, perform an operation\". For example, to multiply each element by three."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1a526124",
   "metadata": {},
   "outputs": [],
   "source": [
    "[element * 3 for element in primes]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "8c829c5b",
   "metadata": {},
   "source": [
    "Note that the word \"element\" above could have been almost any word because we define it by saying `...for element in ...`. You can try the above with a different word, eg `[entry*3 for entry in primes]`."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "acf1e506",
   "metadata": {},
   "source": [
    "All Python statements where you create objects (known as *assignment* statements) have the same form:\n",
    "\n",
    "```\n",
    "object_name = value\n",
    "```\n",
    "\n",
    "When reading that code, say \"object name gets value\" in your head."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "2322fab5",
   "metadata": {},
   "source": [
    "## Comments\n",
    "\n",
    "Python will ignore any text after `#`. This allows to you to write **comments**, text that is ignored by Python but can be read by other humans. We'll sometimes include comments in examples explaining what's happening with the code.\n",
    "\n",
    "Comments can be helpful for briefly describing what the subsequent code does."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c061f9cc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# define primes\n",
    "primes = [1, 2, 3, 5, 7, 11, 13]\n",
    "# multiply primes by 2\n",
    "[el * 2 for el in primes]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "cb49df46",
   "metadata": {},
   "source": [
    "With short pieces of code like this, it is not necessary to leave a command for every single line of code and you should try to use informative names wherever you can because these help readers of your code (likely to be you in the future) understand what is going on!\n",
    "\n",
    "Our advice is to use comments to explain the *why* of your code, not the *how* or the *what*. The *what* and *how* of your code are always possible to figure out, even if it might be tedious, by carefully reading it. If you describe every step in the comments, and then change the code, you will have to remember to update the comments as well (tedious) or it will be confusing when you return to your code in the future.\n",
    "\n",
    "Figuring out *why* something was done is much more difficult, if not impossible. For example, geom_smooth() has an argument called span, that controls the smoothness of the curve, with larger values yielding a smoother curve. Suppose you decide to change the value of span from its default of 0.75 to 0.9: it’s easy for a future reader to understand *what* is happening, but unless you note your thinking in a comment, no one will understand *why* you changed the default.\n",
    "\n",
    "For data analysis code, use comments to explain your overall plan of attack and record important insights as you encounter them. There’s no way to re-capture this knowledge from the code itself."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "9f19d076",
   "metadata": {},
   "source": [
    "## Keeping Track of Variables\n",
    "\n",
    "You can always inspect an already-created object by typing its name into the interactive window:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e77540e0",
   "metadata": {},
   "outputs": [],
   "source": [
    "primes"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "26a8ac97",
   "metadata": {},
   "source": [
    "If you want to know what *type* of object it is, use `type(object)` in the interactive window like this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9dd0fd49",
   "metadata": {},
   "outputs": [],
   "source": [
    "type(primes)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "e533b440",
   "metadata": {},
   "source": [
    "Visual Studio Code has some powerful features to help you keep track of objects:\n",
    "\n",
    "1. At the top of your interactive window, you should see a 'Variables' button. Click it to see a panel appear with all variables that you've defined.\n",
    "2. Hover your mouse over variables you've previously entered into the interactive window; you will see a pop-up that tells you what type of object it is.\n",
    "3. If you start typing a variable name into the interactive window, Visual Studio Code will try to auto-complete the name for you. Press the 'tab' key on your keyboard to accept the top option."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "dac156dd",
   "metadata": {},
   "source": [
    "## What's In A Name?\n",
    "\n",
    "Object (aka \"variable\") names must do the following to be valid in Python:\n",
    "\n",
    "- start with a letter or the underscore character\n",
    "- not start with a number\n",
    "- only contain alpha-numeric characters and underscores (A-z, 0-9, and _)\n",
    "\n",
    "Object names in Python are case-sensitive too, so `age`, `Age` and `AGE` could all be three different variables.\n",
    "\n",
    "When you're naming objects, it's best to make them descriptive so you can keep track of what they are. You’ll need to adopt a convention for multiple words. We recommend snake_case, where you separate lowercase words with `_`. For example, `i_use_snake_case` is a valid snake case name for an object.\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "8df398a0",
   "metadata": {},
   "source": [
    "```{admonition} Exercise\n",
    "Try creating the object `age` and assigning it the value `10`. What happens when you type `Age` into your console?\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4d364f79",
   "metadata": {},
   "source": [
    "Remember that you can always inspect an object that you've created by typing its name again:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a5998cb5",
   "metadata": {},
   "outputs": [],
   "source": [
    "primes"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "82807f98",
   "metadata": {},
   "source": [
    "Make another assignment:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ae55d78e",
   "metadata": {},
   "outputs": [],
   "source": [
    "this_is_a_really_long_name = 2.5"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73c37168",
   "metadata": {},
   "source": [
    "To save yourself time in inspecting this object via the interactive window, you can just begin typing the name (type \"this\") and then hit the <kbd>TAB</kbd> button. Visual Studio Code will autocomplete what you've written using the variables you've defined during your session. This is a top tip to save time!\n",
    "\n",
    "If you're using the interactive console, rather than a notebook, there's another top tip. Let's say you previously ran `this_is_a_really_long_name = 2.5` but you *meant* to set it to 3.5. Don't despair; you don't have to type it all out again. With your cursor in the interactive window, you can simply hit <kbd>↑</kbd> on your keyboard and cycle through previous commands you issued. Change 2.5 to 3.5, hit shift + return, and you'll have redefined your variable.\n",
    "\n",
    "Let's define another variable:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "038c7d52",
   "metadata": {},
   "outputs": [],
   "source": [
    "py_variable = 2 ^ 3"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "446dfa44",
   "metadata": {},
   "source": [
    "Now let's try to inspect it:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5248dbc8",
   "metadata": {},
   "source": [
    "```python\n",
    "py_variabl\n",
    "\n",
    "---------------------------------------------------------------------------\n",
    "NameError                                 Traceback (most recent call last)\n",
    "/Users/aet/Documents/git_projects/python4DS/workflow-basics.ipynb Cell 31 in ()\n",
    "----> 1 py_variabl\n",
    "\n",
    "NameError: name 'py_variabl' is not defined\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e2cf9efc",
   "metadata": {},
   "source": [
    "This illustrates the brilliance and frustration of coding: your IDE (Visual Studio Code) will do tedious computations for you, but, in exchange, you must be precise in your instructions. If not, you’re likely to get an error that says the object you’re looking for was not found. Typos matter; Python can’t read your mind and say, “oh, they probably meant `py_variable` when they typed `py_variabl`”."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "e6f6c2b3",
   "metadata": {},
   "source": [
    "## Calling Functions\n",
    "\n",
    "Python has a large number of built-in functions. You can also import functions from packages (like we did with `np.sin`) or define your own.\n",
    "\n",
    "In coding, a function has inputs, it performs its function, and it returns any outputs. Let's see a simple example of using a built-in function, `sum()`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "97af119d",
   "metadata": {},
   "outputs": [],
   "source": [
    "sum(primes)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "010019c9",
   "metadata": {},
   "source": [
    "The general structure of functions is the function name, followed by brackets, followed by one or more arguments. Sometimes there will also be *keyword arguments*. For example, `sum()` comes with a keyword argument that tells the function to start counting from a specific number. Let's see this in action by starting from ten:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "14ce9b99",
   "metadata": {},
   "outputs": [],
   "source": [
    "sum(primes, start=10)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "68c60946",
   "metadata": {},
   "source": [
    "If you're ever unsure of what a function does, you can call `help()` on it (itself a function):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f5e45616",
   "metadata": {},
   "outputs": [],
   "source": [
    "help(sum)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "93e81f5c",
   "metadata": {},
   "source": [
    "Or, in Visual Studio Code, hover your mouse over the function name.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d380a16b",
   "metadata": {},
   "source": [
    "Just as with variables, code completion works on functions too. Try typing in `su` and hitting tab to see this in action."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e578077",
   "metadata": {},
   "source": [
    "You'll need to be extra careful with objects that are strings (words, sentences, letters, and phrases), because these always need to come with quotation marks around them. You can use single or double quotation marks as you like, but i) the convention is double quotation marks, and ii) it's good to be consistent, whichever you choose. \n",
    "\n",
    "Here's an example of some code that throws an error"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1b95d213",
   "metadata": {},
   "source": [
    "```python\n",
    "x = \"hello\n",
    "\n",
    "  Input In [3]\n",
    "    x = \"hello\n",
    "        ^\n",
    "SyntaxError: unterminated string literal (detected at line 1)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "38d073ce",
   "metadata": {},
   "source": [
    "Again, Visual Studio Code can really help you out here because as soon as you open a double quotation mark, it will have the closing one ready for you."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6af6ea6c",
   "metadata": {},
   "source": [
    "## Exercises\n",
    "\n",
    "1. Why does this code not work?\n",
    "\n",
    "    ```python\n",
    "    my_variable = 10\n",
    "    my_varıable\n",
    "    ```\n",
    "\n",
    "    Look carefully! This may seem like an exercise in pointlessness, but training your brain to notice even the tiniest difference will pay off when programming.\n",
    "\n",
    "2. Tweak each of the following Python commands so that they run correctly: \n",
    "\n",
    "    ```python\n",
    "    import pandas as pd\n",
    "    from palmerpenguins import load_penguins\n",
    "    from lets_pot import *\n",
    "\n",
    "    LetsPlot.setup_html()\n",
    "    penguins = load_penguins()\n",
    "\n",
    "    (\n",
    "        ggplot(\n",
    "            dTA=penguins,\n",
    "            maping=aes(x=\"flipper_length_mm\", y=\"body_mass_g\", color=\"species\"),\n",
    "        )\n",
    "        + geom_smooth(method=\"lm)\n",
    "    )\n",
    "    ```"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "9d7534ecd9fbc7d385378f8400cf4d6cb9c6175408a574f1c99c5269f08771cc"
  },
  "jupytext": {
   "cell_metadata_filter": "-all",
   "encoding": "# -*- coding: utf-8 -*-",
   "formats": "md:myst",
   "main_language": "python"
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  },
  "toc-showtags": true
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
